/** 不包含 devops 的创建（目前集团内部使用） */
import React from 'react';
import PropTypes from 'prop-types';
import { Dialog, Form, Input, Message, Field, Select } from '@teamix/ui';
import { YunxiaoIcon } from '@alife/devops-ui';
import MdEditor from 'components/mdEditor';
import MemberTrigger from 'components/memberTrigger';
import { navigate, navigateHref } from 'utils/router';
import exceed from 'utils/apimap';
import { ENUM, ORGANIZATION_ADMIN_ROLES } from 'utils/constants.js';
import { access } from 'components/accessContainer/util';
import PathEllipsis from 'components/pathEllipsis';
import utils from 'utils';
import './index.scss';
import intl from '../../locale';

const { pathResource, organization } = window.FORCE;

export default class CRModal extends React.Component {
  static propTypes = {
    trigger: PropTypes.element,
    onCancel: PropTypes.func,
    closeModal: PropTypes.func,
    sourceBranch: PropTypes.string,
    title: PropTypes.string,
    isModalOpen: PropTypes.bool,
    cannotChangeProject: PropTypes.bool,
  };

  static defaultProps = {
    trigger: null,
    closeModal: () => {},
    // 默认搜索所有组下库
    cannotChangeProject: false,
  };

  constructor(props) {
    super(props);
    this.field = new Field(this);

    const sourceBranch = this.props.sourceBranch || '';
    const title = this.props.title || '';

    this.state = {
      isModalOpen: false,
      projects: [],
      projectId: null,
      projectPath: null,
      branches: [],
      sourceBranch,
      title,
      targetBranch: '',
      assigneeIdDataSource: [],
      description: '',
      checkMes: '',
      submitting: false,
    };
  }

  static getDerivedStateFromProps(props) {
    if (props.trigger) {
      return {};
    }
    return {
      isModalOpen: props.isModalOpen,
    };
  }

  componentDidMount() {
    // 在库页面是否默认当前库，空库可以默认当前库（错误提示 + 按钮禁用），浏览者权限则不默认当前库。
    if (pathResource && pathResource.id && pathResource.type.toLowerCase() === 'project') {
      this.getRepoInfo(pathResource.id, (projectInfo) => {
        // 非企业管理员 + access_level <= 20 则为浏览者
        const hasAccess =
          access(ORGANIZATION_ADMIN_ROLES, organization.user_role) ||
          Number(projectInfo.access_level) > ENUM.access_level_id.REPORTER;
        if (hasAccess) {
          this.setState({
            projectId: Number(pathResource.id),
            projectPath: pathResource.fullPath,
          });

          // 库内吊顶需要请求所有列表，库内其他不需要
          if (!this.props.cannotChangeProject) {
            this.getAllProjects('', projectInfo);
          }

          this.getBranches(pathResource.id, () => {
            this.setTargetBranch(projectInfo);
          });
        } else {
          this.getAllProjects();
        }
      });
    } else {
      this.getAllProjects();
    }
  }

  // 获取库权限，浏览者不默认当前库
  getRepoInfo = (projectId, callback) => {
    exceed
      .forceFetch({
        api: 'projects.single.get',
        params: { id: projectId },
      })
      .then((result) => {
        callback(result);
      });
  };

  showModal = () => {
    this.setState({
      isModalOpen: true,
    });
  };

  onClose = () => {
    this.setState({
      isModalOpen: false,
    });

    this.props.closeModal();
  };

  onDialogOk = () => {
    if (this.state.submitting) return;
    this.field.validate((errors) => {
      if (!errors) {
        this.setState({ submitting: true });
        let formData = this.field.getValues();
        const { sourceBranch, targetBranch, description } = this.state;
        if (formData.tb_user_ids) {
          formData.tb_user_ids = formData.tb_user_ids.join(',');
        }

        formData = {
          ...formData,
          description,
          source_branch: sourceBranch,
          target_branch: targetBranch,
        };

        this.createCr(formData, () => {
          this.setState({ submitting: false });
        });
      }
    });
  };

  onSourceBranchSelect = (value) => {
    this.setState({ sourceBranch: value });
    const selectedBranches = this.state.branches.filter((b) => b.name === value);
    if (selectedBranches && selectedBranches.length !== 0) {
      let title = selectedBranches[0].commit.message;
      if (title.length > 128) {
        title = `${title.substr(0, 125)}...`;
      }
      this.setState({
        title,
      });

      this.field.setValue('title', title);
      this.field.validate();
    } else {
      // Regard this is a SHA
    }
  };

  onProjectSelect = (value) => {
    const selectedProjects = this.state.projects.filter((p) => p.id === value);
    if (selectedProjects && selectedProjects.length) {
      const selectedProject = selectedProjects[0];
      this.setState({
        projectId: value,
        projectPath: selectedProject.path_with_namespace,
      });

      this.getRepoInfo(selectedProject.id, (projectInfo) => {
        this.getBranches(selectedProject.id, () => {
          this.setTargetBranch(projectInfo);
          // this.getCodeReviewSetting(selectedProject.id);
        });
      });
    }
  };

  // 搜索代码库并获取列表
  onProjectSearch = (search) => {
    exceed
      .fetch({
        api: 'projects.getAuthWriteList',
        data: {
          search,
          per_page: 50,
          order_by: 'last_activity_at',
          sort: 'desc',
        },
      })
      .then((list) => {
        list.shift();
        this.setState({
          projects: list,
        });
      });
  };

  // 获取分支
  getBranches = (projectId, callback) => {
    exceed
      .forceFetch({
        api: 'projects.all.branches.search',
        params: { id: projectId },
      })
      .then((result) => {
        if (result.list) {
          if (result.list.length) {
            this.setState({
              branches: result.list,
              isEmpty: false,
            });

            // 在分支页面创建代码评审的场景，查询分支ok后，再设置默认分支
            if (this.state.sourceBranch) {
              this.onSourceBranchSelect(this.state.sourceBranch);
            }
            this.field.setError('projectId', '');
            callback && callback();
          } else {
            this.setState({
              isEmpty: true,
            });

            // 返回数据为[]则为空库，重置数据
            const sourceBranch = this.props.sourceBranch || '';
            const title = this.props.title || '';
            this.setState({
              branches: [],
              sourceBranch,
              title,
              targetBranch: '',
              assigneeIdDataSource: [],
              checkMes: '',
            });

            this.field.setValue('targetBranch', '');
            this.field.setValue('sourceBranch', '');
            this.field.setValue('title', '');
            this.field.setError(
              'projectId',
              intl.get({
                id: 'code-assets.components.createCRModal.createWithoutDevOps.TheSelectedDatabaseIsEmpty',
                defaultMessage: '所选库为空库，不能创建合并请求',
              }),
            );
            this.field.setValue('tb_user_ids', []);
          }
        }
      });
  };

  setTargetBranch = (projectInfo) => {
    const targetBranch = projectInfo.default_branch || 'master';
    // 设置默认分支
    this.field.setValue('targetBranch', targetBranch);
    this.onTargetBranchChange(targetBranch);
  };

  // 全局下获取代码库 curProjectInfo存在时，判断返回数据是否包含当前库，没有则将当前库放在首位
  getAllProjects = (search, curProjectInfo) => {
    exceed
      .fetch({
        api: 'projects.getAuthWriteList',
        data: {
          search,
          per_page: 50,
          order_by: 'last_activity_at',
          sort: 'desc',
        },
      })
      .then((result) => {
        result.shift();
        if (curProjectInfo) {
          if (result.findIndex((item) => item.id === curProjectInfo.id) === -1) {
            result.unshift(curProjectInfo);
          }
          this.field.setValue('projectId', Number(pathResource.id));
        }

        this.setState({
          projects: result,
        });
      });
  };

  // 获取并设置默认评审人
  getCodeReviewSetting = (projectId, branch) => {
    if (!projectId) {
      return;
    }
    exceed
      .forceFetch({
        api: 'codereview.setting.get',
        params: {
          id: projectId,
        },

        data: {
          branch: branch || pathResource.defaultBranch,
        },
      })
      .then((result) => {
        this.setState(
          {
            assigneeIdDataSource: result.default_assignees,
          },

          () => {
            const target_branch = branch || pathResource.defaultBranch;
            if (target_branch) {
              this.checkReviewer({
                tb_user_ids: result.default_assignees.map((item) => item.tb_user_id).join(','),
                target_branch,
              });
            }
          },
        );

        this.field.setValue(
          'tb_user_ids',
          result.default_assignees.map((item) => item.tb_user_id),
        );
      });
  };

  // 代码库搜索框
  getProjectFormItemJsx() {
    const { init } = this.field;
    const { cannotChangeProject } = this.props;
    let result = <Input />;
    if (cannotChangeProject) {
      const nameArr = pathResource.fullName.split('/');
      const projectName = nameArr[nameArr.length - 1].trim();
      result = <Input readOnly disabled value={projectName || ''} />;
    } else {
      result = (
        <Select
          showSearch
          placeholder={intl.get({
            id: 'code-assets.components.createCRModal.createWithoutDevOps.EnterACodeLibraryName',
            defaultMessage: '请输入代码库名以搜索',
          })}
          dataSource={this.state.projects.map((p) => ({
            label: p.name,
            value: p.id,
            name_with_namespace: p.name_with_namespace,
          }))}
          onSearch={this.onProjectSearch}
          filterLocal={false}
          {...init('projectId', {
            initValue: this.state.projectId,
            rules: [
              {
                required: true,
                message: intl.get({
                  id: 'code-assets.src.utils.locale.ThisParameterIsRequired',
                  defaultMessage: '该项为必填项',
                }),
              },
            ],
            props: {
              onChange: (value) => {
                this.onProjectSelect(value);
              },
            },
          })}
          popupProps={{
            className: 'at-path-select-popup',
          }}
          itemRender={(item) => {
            const path = item.name_with_namespace;
            return <PathEllipsis path={utils.getGroupPath(path)} />;
          }}
        />
      );
    }

    return result;
  }

  onChangevalue = (value) => {
    this.setState({ description: value });
  };

  onTargetBranchChange = (value) => {
    this.setState({ targetBranch: value });
    this.getCodeReviewSetting(this.state.projectId, value);
  };

  onMemberChange = (value) => {
    this.setState(
      {
        assigneeIdDataSource: value,
      },

      () => {
        this.checkReviewer({
          tb_user_ids: value.map((item) => item._userId || item.tb_user_id).join(','),
          target_branch: this.state.targetBranch,
        });
      },
    );

    this.field.setValue(
      'tb_user_ids',
      value.map((item) => item._userId || item.tb_user_id),
    );
  };

  // 校验可点通过的评审者是否>=添加的评审者
  checkReviewer(data) {
    exceed
      .fetch({
        api: 'project.mr.check_reviewer',
        params: {
          projectId: this.state.projectId,
        },

        data: { ...data, lazy_init: true },
      })
      .then((result) => {
        if (result.pass === false) {
          this.setState({
            checkMes: result,
          });
        } else {
          this.setState({
            checkMes: '',
          });
        }
      });
  }

  // 创建CR
  createCr(formData, cb) {
    exceed
      .fetch({
        api: 'project.mr.post',
        params: {
          projectId: this.state.projectId,
        },

        data: { ...formData, lazy_init: true },
      })
      .then((cr) => {
        Message.success({
          title: intl.get({
            id: 'code-assets.components.createCRModal.createWithoutDevOps.NewReviewSucceeded',
            defaultMessage: '新建评审成功',
          }),
        });

        cb && cb();
        this.onClose();
        // 错误页面直接跳转
        const isErrorPage = window.ERROR && window.ERROR.errorCode;
        if (isErrorPage) {
          navigateHref(`/${this.state.projectPath}/merge_request/${cr.id}`);
        } else {
          navigate(`/${this.state.projectPath}/merge_request/${cr.id}`, {
            state: { forceUpdate: true },
          });
        }
      })
      .fail(() => {
        cb && cb();
      });
  }

  // 合并请求名称校验
  nameValidator = (rule, value, callback) => {
    if (!value) {
      callback();
      return;
    }
    if (value.length > 256) {
      callback(
        intl.get({
          id: 'code-assets.components.createCRModal.createWithoutDevOps.TheMergeRequestNameCannot',
          defaultMessage: '合并请求名称不能超过256字符',
        }),
      );
    } else {
      callback();
    }
  };

  render() {
    const { field } = this;
    const { init } = this.field;
    const { checkMes, projectId, isEmpty } = this.state;
    return (
      <React.Fragment>
        {this.state.isModalOpen ? (
          <Dialog
            visible
            // autoFocus={!this.props.sourceBranch}
            onOk={this.onDialogOk}
            onCancel={this.onClose}
            onClose={this.onClose}
            title={intl.get({
              id: 'code-assets.components.createCRModal.createWithoutDevOps.CreateMergeRequest',
              defaultMessage: '新建合并请求',
            })}
            okProps={{ loading: this.state.submitting, disabled: isEmpty }}
            style={{
              width: 680,
            }}
          >
            <Form className="cr-create-form" field={field} labelAlign="top">
              <Form.Item
                label={intl.get({
                  id: 'code-assets.components.createCRModal.createWithoutDevOps.CodeBase',
                  defaultMessage: '代码库',
                })}
                className="cr-repo"
                required
              >
                {this.getProjectFormItemJsx()}
              </Form.Item>
              <div className="cr-create-form-branches">
                <Form.Item
                  label={intl.get({
                    id: 'code-assets.components.createCRModal.createWithoutDevOps.SourceBranch',
                    defaultMessage: '源分支',
                  })}
                  className="cr-source-branch"
                  required
                >
                  <Select
                    showSearch
                    dataSource={this.state.branches.map((item) => ({
                      label: item.name,
                      value: item.name,
                    }))}
                    {...init('sourceBranch', {
                      initValue: this.state.sourceBranch,
                      rules: [
                        {
                          required: true,
                          message: intl.get({
                            id: 'code-assets.src.utils.locale.ThisParameterIsRequired',
                            defaultMessage: '该项为必填项',
                          }),
                        },
                      ],
                      props: {
                        onChange: (value) => {
                          this.onSourceBranchSelect(value);
                        },
                      },
                    })}
                  />
                </Form.Item>
                <YunxiaoIcon type="arrow-right-line" className="cr-branch-icon" />

                <Form.Item
                  label={intl.get({
                    id: 'code-assets.components.createCRModal.createWithoutDevOps.TargetBranch',
                    defaultMessage: '目标分支',
                  })}
                  className="cr-target-branch"
                  required
                >
                  <Select
                    showSearch
                    dataSource={this.state.branches.map((item) => ({
                      label: item.name,
                      value: item.name,
                    }))}
                    {...init('targetBranch', {
                      initValue: this.state.targetBranch,
                      rules: [
                        {
                          required: true,
                          message: intl.get({
                            id: 'code-assets.src.utils.locale.ThisParameterIsRequired',
                            defaultMessage: '该项为必填项',
                          }),
                        },
                      ],
                      props: {
                        onChange: (value) => {
                          this.onTargetBranchChange(value);
                        },
                      },
                    })}
                  />
                </Form.Item>
              </div>
              <Form.Item
                label={intl.get({
                  id: 'code-assets.components.createCRModal.createWithoutDevOps.Title',
                  defaultMessage: '标题',
                })}
                required
              >
                <Input
                  placeholder={intl.get({
                    id: 'code-assets.components.createCRModal.createWithoutDevOps.EnterATitle',
                    defaultMessage: '请输入标题',
                  })}
                  {...init('title', {
                    initValue: this.state.title,
                    rules: [
                      {
                        required: true,
                        message: intl.get({
                          id: 'code-assets.src.utils.locale.ThisParameterIsRequired',
                          defaultMessage: '该项为必填项',
                        }),
                      },
                      { validator: this.nameValidator },
                    ],
                  })}
                  maxLength={256}
                  hasLimitHint
                />
              </Form.Item>
              <Form.Item
                label={intl.get({
                  id: 'code-assets.components.createCRModal.createWithoutDevOps.Description',
                  defaultMessage: '描述',
                })}
              >
                <MdEditor
                  placeholder={intl.get({
                    id: 'code-assets.components.createCRModal.createWithoutDevOps.EnterADescription',
                    defaultMessage: '请输入描述',
                  })}
                  size="small"
                  onChangevalue={this.onChangevalue}
                  noAutoFocus
                  textareaStyle={{ height: '64px', padding: '4px 8px' }}
                />
              </Form.Item>
              <Form.Item
                label={intl.get({
                  id: 'code-assets.components.createCRModal.createWithoutDevOps.Reviewer',
                  defaultMessage: '评审人',
                })}
              >
                <MemberTrigger
                  useExtraMember="project"
                  pathResourceId={projectId}
                  onChange={this.onMemberChange}
                  value={this.state.assigneeIdDataSource}
                  align="bl tl"
                  followTrigger={false}
                  multiple
                />

                {checkMes ? <Message type="warning" title={checkMes.msg} shape="addon" /> : null}
              </Form.Item>
            </Form>
          </Dialog>
        ) : null}
        {!!this.props.trigger &&
          React.cloneElement(this.props.trigger, {
            onClick: (e) => {
              this.props.trigger.props.onClick && this.props.trigger.props.onClick(e);
              this.showModal();
            },
          })}
      </React.Fragment>
    );
  }
}
